﻿// <copyright file="ARule.cs" company="Beuth Hochschule für Technik">
// Breakdown - Configure your Windows 7 Firewall
// Copyright (C) 2009 Stefan "dersteps@gmail.com" Matyba
// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; 
// either version 3 of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program; if not, see http://www.gnu.org/licenses/.
// </copyright>
// <author>Stefan Matyba</author>
// <email>dersteps@gmail.com</email>
// <date>2009-10-20</date>
// <summary>Breakdown Application Logic - Base class for firewall rules</summary>

namespace Breakdown.Logic
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Text;
    using Breakdown.Aspects;
    
    /// <summary>
    /// The abstract base class for all firewall rules
    /// </summary>
    [Logged]
    public abstract class ARule : IObservable
    {
        /// <summary>
        /// The name of this firewall rule
        /// </summary>
        private string _name = string.Empty;

        /// <summary>
        /// A short description of this rule
        /// </summary>
        private string _description = string.Empty;

        /// <summary>
        /// Determines whether or not this rule is currently enabled
        /// </summary>
        private bool _enabled = true;

        /// <summary>
        /// Determines the action of this rule
        /// </summary>
        private RuleAction _action = RuleAction.None;

        /// <summary>
        /// Determines to which profile(s) this rule applies
        /// </summary>
        private RuleAppliances _appliances = RuleAppliances.None;

        /// <summary>
        /// List of observers
        /// </summary>
        private Collection<IObserver> _observers = new Collection<IObserver>();      

        /// <summary>
        /// Gets or sets the rule's name
        /// </summary>
        [Logged]
        public string Name
        {
            get { return this._name; }
            set 
            { 
                this._name = value;
                this.Notify();
            }
        }

        /// <summary>
        /// Gets or sets the rule's description
        /// </summary>
        public string Description
        {
            get { return this._description; }
            set 
            {
                this._description = value;
                this.Notify();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the rule is enabled
        /// </summary>
        public bool Enabled
        {
            get { return this._enabled; }
            set 
            { 
                this._enabled = value;
                this.Notify();
            }
        }

        /// <summary>
        /// Gets or sets the rule's action
        /// </summary>
        public RuleAction Action
        {
            get { return this._action; }
            set
            {
                this._action = value;
                this.Notify();
            }
        }

        /// <summary>
        /// Gets or sets the rule's appliances
        /// </summary>
        public RuleAppliances Appliances
        {
            get { return this._appliances; }
            set 
            {
                this._appliances = value;
                this.Notify();
            }
        }

        /// <summary>
        /// Gets the list of the rule's observers
        /// </summary>
        public Collection<IObserver> Observers
        {
            get { return this._observers; }
        }

        /// <summary>
        /// Gets or sets the IInterfaceAffector that is part of the firewall rule
        /// </summary>
        public abstract IInterfaceAffector InterfaceAffector { get; set; }

        /// <summary>
        /// Gets or sets the Scope that is part of the firewall rule
        /// </summary>
        public abstract IScoped Scope { get; set; }

        /// <summary>
        /// Gets or sets the Program Affector that is part of the firewall rule
        /// </summary>
        public abstract IProgramAffector ProgramAffector { get; set; }

        /// <summary>
        /// Gets or sets the Service Affector that is part of this firewall rule
        /// </summary>
        public abstract IServiceAffector ServiceAffector { get; set; }
        
        #region Methods

        /// <summary>
        /// Toggles whether or not the rule is enabled
        /// </summary>
        public void Toggle()
        {
            this.Enabled = !this.Enabled;
        }     

        /// <summary>
        /// Registers a new observer to the rule
        /// </summary>
        /// <param name="observer">The IObserver to register</param>
        /// <returns>Amount of observers registered (including the new one)</returns>
        public int Register(IObserver observer)
        {
            this._observers.Add(observer);
            this.Notify();
            return this._observers.Count<IObserver>();
        }

        /// <summary>
        /// Removes an observer from the rule
        /// </summary>
        /// <param name="observer">The IObserver to remove</param>
        /// <returns>Amount of observers registered after removal</returns>
        public int Remove(IObserver observer)
        {
            this._observers.Remove(observer);
            this.Notify();
            return this._observers.Count<IObserver>();
        }

        /// <summary>
        /// Removes all observers from the rule
        /// </summary>
        public void Orphan()
        {
            this._observers.Clear();
        }

        /// <summary>
        /// Notifies all observers
        /// </summary>
        protected internal void Notify()
        {
            foreach (IObserver o in this._observers)
            {
                o.Update(this);
            }
        }

        #endregion
    }
}
